//
//  JRGridCollectionView.m
//  SafeAreaTest
//
//  Created by dingjiarui on 2017/11/16.
//  Copyright © 2017年 dingjiarui. All rights reserved.
//

#import "JRGridCollectionView.h"
#import "JRGridCollectionViewLayout.h"

@interface JRGridCollectionView () <UICollectionViewDelegate, UICollectionViewDataSource>

@property (nonatomic, weak) UICollectionView *collectionView;

@property (nonatomic, copy) JRGridCollectionViewDequeueReusableCellBlock dequeueReusableCellBlock;
@property (nonatomic, copy) JRGridCollectionViewCellConfigureBlock cellConfigureBlock;
@property (nonatomic, copy) JRGridCollectionViewSizeForItemBlock sizeForItemBlock;
@property (nonatomic, copy) JRGridCollectionViewDidSelectItemAtIndexPathBlock didSelectItemAtIndexPathBlock;

/** SupplementaryView */
@property (nonatomic, copy) JRGridCollectionViewDequeueReusableSupplementaryViewlBlock dequeueReusableSupplementaryViewlBlock;
@property (nonatomic, copy) JRGridCollectionViewSupplementaryViewConfigureBlock supplementaryViewConfigureBlock;

@end

@implementation JRGridCollectionView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self customInit];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self customInit];
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    if (self.collectionHeaderView) {
        CGRect rect = self.collectionHeaderView.frame;
        rect.origin = CGPointMake(0, -self.collectionView.contentInset.top);
        rect.size.width = CGRectGetWidth(self.collectionView.frame);
        self.collectionHeaderView.frame = rect;
    }
    if (self.collectionFooterView) {
        CGRect rect = self.collectionFooterView.frame;
        rect.origin = CGPointMake(0, CGRectGetHeight(self.collectionView.frame)-CGRectGetHeight(rect)-self.collectionView.contentInset.top);
        rect.size.width = CGRectGetWidth(self.frame);
        self.collectionFooterView.frame = rect;
    }
}


- (void)customInit
{
    [self UI_init];
    
}

- (void)UI_init
{
    /* UI */
    JRGridCollectionViewLayout *collectionViewLayout = [[JRGridCollectionViewLayout alloc] init];
    self.collectionViewLayout = collectionViewLayout;
    
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:collectionViewLayout];
    collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    collectionView.backgroundColor = [UIColor clearColor];
    collectionView.dataSource = self;
    collectionView.delegate = self;
    if (@available(iOS 11.0, *)){
        [collectionView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
    }
    [self addSubview:collectionView];
    self.collectionView = collectionView;
}

- (void)callbackCellIdentifier:(JRGridCollectionViewDequeueReusableCellBlock)aCellIdentifier
                 configureCell:(JRGridCollectionViewCellConfigureBlock)aConfigureCell
      didSelectItemAtIndexPath:(JRGridCollectionViewDidSelectItemAtIndexPathBlock)aDidSelectItemAtIndexPath
{
    [self callbackCellIdentifier:aCellIdentifier
                   configureCell:aConfigureCell
                     sizeForItem:nil
        didSelectItemAtIndexPath:aDidSelectItemAtIndexPath
     supplementaryViewIdentifier:nil
 supplementaryViewConfigureBlock:nil];
}

- (void)callbackCellIdentifier:(JRGridCollectionViewDequeueReusableCellBlock)aCellIdentifier
                 configureCell:(JRGridCollectionViewCellConfigureBlock)aConfigureCell
                   sizeForItem:(JRGridCollectionViewSizeForItemBlock)aSizeForItem
      didSelectItemAtIndexPath:(JRGridCollectionViewDidSelectItemAtIndexPathBlock)aDidSelectItemAtIndexPath
{
    [self callbackCellIdentifier:aCellIdentifier
                   configureCell:aConfigureCell
                     sizeForItem:aSizeForItem
        didSelectItemAtIndexPath:aDidSelectItemAtIndexPath
     supplementaryViewIdentifier:nil
 supplementaryViewConfigureBlock:nil];
}

- (void)callbackCellIdentifier:(JRGridCollectionViewDequeueReusableCellBlock)aCellIdentifier
                 configureCell:(JRGridCollectionViewCellConfigureBlock)aConfigureCell
      didSelectItemAtIndexPath:(JRGridCollectionViewDidSelectItemAtIndexPathBlock)aDidSelectItemAtIndexPath
   supplementaryViewIdentifier:(JRGridCollectionViewDequeueReusableSupplementaryViewlBlock)aSupplementaryViewIdentifier
supplementaryViewConfigureBlock:(JRGridCollectionViewSupplementaryViewConfigureBlock)aSupplementaryViewConfigureBlock
{
    [self callbackCellIdentifier:aCellIdentifier
                   configureCell:aConfigureCell
                     sizeForItem:nil
        didSelectItemAtIndexPath:aDidSelectItemAtIndexPath
     supplementaryViewIdentifier:aSupplementaryViewIdentifier
 supplementaryViewConfigureBlock:aSupplementaryViewConfigureBlock];
}

- (void)callbackCellIdentifier:(JRGridCollectionViewDequeueReusableCellBlock)aCellIdentifier
                 configureCell:(JRGridCollectionViewCellConfigureBlock)aConfigureCell
                   sizeForItem:(JRGridCollectionViewSizeForItemBlock)aSizeForItem
      didSelectItemAtIndexPath:(JRGridCollectionViewDidSelectItemAtIndexPathBlock)aDidSelectItemAtIndexPath
   supplementaryViewIdentifier:(JRGridCollectionViewDequeueReusableSupplementaryViewlBlock)aSupplementaryViewIdentifier
supplementaryViewConfigureBlock:(JRGridCollectionViewSupplementaryViewConfigureBlock)aSupplementaryViewConfigureBlock
{
    self.dequeueReusableCellBlock = aCellIdentifier;
    self.cellConfigureBlock = aConfigureCell;
    self.sizeForItemBlock = aSizeForItem;
    self.didSelectItemAtIndexPathBlock = aDidSelectItemAtIndexPath;
    
    self.dequeueReusableSupplementaryViewlBlock = aSupplementaryViewIdentifier;
    self.supplementaryViewConfigureBlock = aSupplementaryViewConfigureBlock;
}

- (void)registerClass:(nullable Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier
{
    [self.collectionView registerClass:cellClass forCellWithReuseIdentifier:identifier];
}
- (void)registerNib:(nullable UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier
{
    [self.collectionView registerNib:nib forCellWithReuseIdentifier:identifier];
}

- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier
{
    [self.collectionView registerClass:viewClass forSupplementaryViewOfKind:elementKind withReuseIdentifier:identifier];
}
- (void)registerNib:(nullable UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier
{
    [self.collectionView registerNib:nib forSupplementaryViewOfKind:kind withReuseIdentifier:identifier];
}

- (UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return [self.collectionView cellForItemAtIndexPath:indexPath];
}

- (NSArray<UICollectionViewCell *> *)visibleCells
{
    return self.collectionView.visibleCells;
}

- (NSArray<NSIndexPath *> *)indexPathsForVisibleItems
{
    return self.collectionView.indexPathsForVisibleItems;
}

- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion // allows multiple insert/delete/reload/move calls to be animated simultaneously. Nestable.
{
    [self.collectionView performBatchUpdates:updates completion:completion];
}

- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath
{
    [self.collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
}
- (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(9.0)) // returns NO if reordering was prevented from beginning - otherwise YES
{
    return [self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath];
}

- (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition API_AVAILABLE(ios(9.0))
{
    [self.collectionView updateInteractiveMovementTargetPosition:targetPosition];
}

- (void)endInteractiveMovement API_AVAILABLE(ios(9.0))
{
    [self.collectionView endInteractiveMovement];
}

- (void)cancelInteractiveMovement API_AVAILABLE(ios(9.0))
{
    [self.collectionView cancelInteractiveMovement];
}
#pragma mark - headerView/footerView
- (void)setCollectionHeaderView:(UIView *)collectionHeaderView
{
    if (_collectionHeaderView) {
        [_collectionHeaderView removeFromSuperview];
        UIEdgeInsets insets = self.collectionView.contentInset;
        insets.top = 0;
        self.collectionView.contentInset = insets;
        self.collectionView.scrollIndicatorInsets = insets;
    }
    _collectionHeaderView = collectionHeaderView;
    
    if (collectionHeaderView) {
        [self.collectionView addSubview:collectionHeaderView];
        UIEdgeInsets insets = self.collectionView.contentInset;
        insets.top = CGRectGetHeight(collectionHeaderView.frame);
        self.collectionView.contentInset = insets;
        self.collectionView.scrollIndicatorInsets = insets;
    }
}

- (void)setCollectionFooterView:(UIView *)collectionFooterView
{
    if (_collectionFooterView) {
        [_collectionFooterView removeFromSuperview];
        UIEdgeInsets insets = self.collectionView.contentInset;
        insets.bottom = 0;
        self.collectionView.contentInset = insets;
        self.collectionView.scrollIndicatorInsets = insets;
    }
    _collectionFooterView = collectionFooterView;
    
    if (collectionFooterView) {
        [self.collectionView addSubview:collectionFooterView];
        UIEdgeInsets insets = self.collectionView.contentInset;
        insets.bottom = CGRectGetHeight(collectionFooterView.frame);
        self.collectionView.contentInset = insets;
        self.collectionView.scrollIndicatorInsets = insets;
    }
}

#pragma mark - UICollectionViewDataSource
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
    
    NSArray *subDataSources = self.dataSources[indexPath.section];
    id model = subDataSources[indexPath.row];
    
    NSString *JRGridCollectionViewCellIdentifier = nil;
    if (self.dequeueReusableCellBlock) {
        JRGridCollectionViewCellIdentifier = self.dequeueReusableCellBlock(indexPath, model);
    }
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:JRGridCollectionViewCellIdentifier forIndexPath:indexPath];
    
    if (self.cellConfigureBlock) {
        self.cellConfigureBlock(indexPath, model, cell);
    }
    
    return cell;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *supplementaryView = nil;
    NSString *LFGridCollectionViewSupplementaryViewIdentifier = nil;
    if (self.dequeueReusableSupplementaryViewlBlock) {
        LFGridCollectionViewSupplementaryViewIdentifier = self.dequeueReusableSupplementaryViewlBlock(indexPath, kind);
    }
    if (LFGridCollectionViewSupplementaryViewIdentifier) {
        supplementaryView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:LFGridCollectionViewSupplementaryViewIdentifier forIndexPath:indexPath];
    }
    
    if (supplementaryView && self.supplementaryViewConfigureBlock) {
        self.supplementaryViewConfigureBlock(indexPath, supplementaryView);
    }
    
    return supplementaryView;
}

- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    
    NSArray *subDataSources = self.dataSources[section];
    return subDataSources.count;
    
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return self.dataSources.count;
}

#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *subDataSources = self.dataSources[indexPath.section];
    id model = subDataSources[indexPath.row];
    if (self.didSelectItemAtIndexPathBlock) {
        self.didSelectItemAtIndexPathBlock(indexPath, model);
    }
}

- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self.delegate respondsToSelector:@selector(jrGridcollectionView:canMoveItemAtIndexPath:)]) {
        return [self.delegate jrGridcollectionView:self canMoveItemAtIndexPath:indexPath];
    }
    return NO;
}

- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath
{
    if ([self.delegate respondsToSelector:@selector(jrGridcollectionView:moveItemAtIndexPath:toIndexPath:)]) {
        return [self.delegate jrGridcollectionView:self moveItemAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath];
    }
}

#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    NSArray *subDataSources = self.dataSources[indexPath.section];
    id model = subDataSources[indexPath.row];
    
    if (self.sizeForItemBlock) {
        return self.sizeForItemBlock(indexPath, model);
    }
    return self.collectionViewLayout.itemSize;
}

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if ([self.delegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
        [self.delegate scrollViewDidScroll:scrollView];
    }
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if ([self.delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) {
        [self.delegate scrollViewWillBeginDragging:scrollView];
    }
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    if ([self.delegate respondsToSelector:@selector(scrollViewWillEndDragging: withVelocity:targetContentOffset:)]) {
        [self.delegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
    }
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if ([self.delegate respondsToSelector:@selector(scrollViewDidEndDragging: willDecelerate:)]) {
        [self.delegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
    }
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    if ([self.delegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) {
        [self.delegate scrollViewWillBeginDecelerating:scrollView];
    }
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if ([self.delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) {
        [self.delegate scrollViewDidEndDecelerating:scrollView];
    }
}

#pragma mark - UIScrollView setter/getter
- (void)setBounces:(BOOL)bounces
{
    self.collectionView.bounces = bounces;
}
- (BOOL)bounces
{
    return self.collectionView.bounces;
}

- (void)setContentOffset:(CGPoint)contentOffset
{
    [self.collectionView setContentOffset:contentOffset];
}
- (CGPoint)contentOffset
{
    return self.collectionView.contentOffset;
}

- (void)setContentSize:(CGSize)contentSize
{
    [self.collectionView setContentSize:contentSize];
}
- (CGSize)contentSize
{
    return self.collectionView.contentSize;
}

- (void)setContentInset:(UIEdgeInsets)contentInset
{
    [self.collectionView setContentInset:contentInset];
}
- (UIEdgeInsets)contentInset
{
    return self.collectionView.contentInset;
}

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
    [self.collectionView setContentOffset:contentOffset animated:animated];
}
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
{
    [self.collectionView scrollRectToVisible:rect animated:animated];
}
- (NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point {
    return [self.collectionView indexPathForItemAtPoint:point];
}
#pragma mark - UICollectionView setter/getter
- (void)setPagingEnabled:(BOOL)pagingEnabled
{
    self.collectionView.pagingEnabled = pagingEnabled;
}
- (BOOL)isPagingEnabled
{
    return self.collectionView.isPagingEnabled;
}

- (void)setShowsVerticalScrollIndicator:(BOOL)showsVerticalScrollIndicator
{
    self.collectionView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
}
- (BOOL)showsVerticalScrollIndicator
{
    return self.collectionView.showsVerticalScrollIndicator;
}

- (void)setShowsHorizontalScrollIndicator:(BOOL)showsHorizontalScrollIndicator
{
    self.collectionView.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
}
- (BOOL)showsHorizontalScrollIndicator
{
    return self.collectionView.showsHorizontalScrollIndicator;
}

- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated
{
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];
}

- (void)reloadData
{
    [self.collectionView reloadData];
}

- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
{
    [self.collectionView insertItemsAtIndexPaths:indexPaths];
}
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
{
    [self.collectionView deleteItemsAtIndexPaths:indexPaths];
}
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
{
    [self.collectionView reloadItemsAtIndexPaths:indexPaths];
}

#pragma mark - UICollectionViewFlowLayout setter/getter
- (void)setCollectionViewLayout:(UICollectionViewFlowLayout *)collectionViewLayout
{
    self.collectionView.collectionViewLayout = collectionViewLayout;
    if ([collectionViewLayout isKindOfClass:[UICollectionViewFlowLayout class]]) {
        _collectionViewLayout = collectionViewLayout;
    } else {
        _collectionViewLayout = nil;
    }
}
- (void)setMinimumLineSpacing:(CGFloat)minimumLineSpacing
{
    self.collectionViewLayout.minimumLineSpacing = minimumLineSpacing;
}
- (CGFloat)minimumLineSpacing
{
    return self.collectionViewLayout.minimumLineSpacing;
}

- (void)setMinimumInteritemSpacing:(CGFloat)minimumInteritemSpacing
{
    self.collectionViewLayout.minimumInteritemSpacing = minimumInteritemSpacing;
}
- (CGFloat)minimumInteritemSpacing
{
    return self.collectionViewLayout.minimumInteritemSpacing;
}

- (void)setItemSize:(CGSize)itemSize
{
    self.collectionViewLayout.itemSize = itemSize;
}
- (CGSize)itemSize
{
    return self.collectionViewLayout.itemSize;
}

- (void)setEstimatedItemSize:(CGSize)estimatedItemSize
{
    self.collectionViewLayout.estimatedItemSize = estimatedItemSize;
}
- (CGSize)estimatedItemSize
{
    return self.collectionViewLayout.estimatedItemSize;
}

- (void)setScrollDirection:(UICollectionViewScrollDirection)scrollDirection
{
    self.collectionViewLayout.scrollDirection = scrollDirection;
}
- (UICollectionViewScrollDirection)scrollDirection
{
    return self.collectionViewLayout.scrollDirection;
}

- (void)setHeaderReferenceSize:(CGSize)headerReferenceSize
{
    self.collectionViewLayout.headerReferenceSize = headerReferenceSize;
}
- (CGSize)headerReferenceSize
{
    return self.collectionViewLayout.headerReferenceSize;
}

- (void)setFooterReferenceSize:(CGSize)footerReferenceSize
{
    self.collectionViewLayout.footerReferenceSize = footerReferenceSize;
}
- (CGSize)footerReferenceSize
{
    return self.collectionViewLayout.footerReferenceSize;
}

- (void)setSectionInset:(UIEdgeInsets)sectionInset
{
    self.collectionViewLayout.sectionInset = sectionInset;
}
- (UIEdgeInsets)sectionInset
{
    return self.collectionViewLayout.sectionInset;
}

@end
